﻿#region Using

using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

#endregion

namespace Vk.Utils
{
    /// <summary>
    ///     Парсер XElement
    /// </summary>
    public static class XElementParser
    {
        /// <summary>
        /// Извлекает DateTime из указанного узла
        /// </summary>
        public static DateTime? DateTime(this XElement node)
        {
            try
            {
                return new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds((double)node.Int());
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        ///     Извлекает строку из указанного узла
        /// </summary>
        public static string String(this XElement node)
        {
            try
            {
                return Convert.ToString(node.Value);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        ///     Извлекает 16-битное число из указанного узла
        /// </summary>
        public static short? Short(this XElement node)
        {
            try
            {
                return Convert.ToInt16(node.Value);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        ///     Извлекает 32-битное число из указанного узла
        /// </summary>
        public static int? Int(this XElement node)
        {
            try
            {
                return Convert.ToInt32(node.Value);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        ///     Извлекает Double из указанного узла
        /// </summary>
        public static double? Double(this XElement node)
        {
            try
            {
                return Convert.ToDouble(node.Value);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        ///     Извлекает Float из указанного узла
        /// </summary>
        public static float? Float(this XElement node)
        {
            try
            {
                return Convert.ToSingle(node.Value);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        ///     Извлекает Bool из указанного узла
        /// </summary>
        public static bool? Bool(this XElement node)
        {
            //Проверка, можно ли значение XElement преобразовать в bool
            if (node.Value != "1" & node.Value != "0")
            {
                return null;
            }

            return (node.Value == "1");
        }

        /// <summary>
        ///     Превращает строкове значение узла в эквивалентное значение перечисления
        /// </summary>
        /// <param name="enumType">
        /// Тип перечисления
        /// </param>
        /// <example>
        /// <code>XElement.Enum(typeof(ConsoleKey))</code>
        /// </example>
        public static Enum Enum(this XElement node, Type enumType)
        {
            try
            {
                if (node == null)
                    throw new ArgumentNullException("node");
                {
                    var names = node.Value.Split(char.Parse("_"));
                    names = names.Select((name) =>
                    {
                        if (name.Length <= 1)
                        {
                            return name.ToUpperInvariant();
                        }
                        var first = name.First();
                        return char.ToUpper(first) + name.Substring(1);
                    }).ToArray();
                    return
                        (Enum)
                            System.Enum.Parse(enumType, string.Join("", names));
                }
            }
            catch
            {
                return null;
            }
        }
    }
}